<?php
/**
 * Created by PhpStorm.
 * User: whwyy
 * Date: 2018/4/27 0027
 * Time: 11:00
 */

namespace BeReborn\Cache;


use BeReborn\Base\Component;
use BeReborn\Base\Config;
use BeReborn\Event\Event;
use BeReborn\Cache\Export;
use BeReborn\Cache\Implode;
use BeReborn\Exception\ComponentException;
use BeReborn\Exception\ConfigException;
use BeReborn\Pool\RedisClient;
use BeReborn\Service\Common\ServerRequest;
use BeReborn\Service\Common\ServerTask;
use Exception;
use Swoole\Coroutine;

/**
 * Class Redis
 * @package BeReborn\Cache
 * @see \Redis
 */
class Redis extends Component
{
    public $host = '127.0.0.1';
    public $auth = 'xl.2005113426';
    public $port = 6973;
    public $databases = 0;
    public $timeout = -1;
    public $prefix = 'idd';

    /**
     * @throws Exception
     */
    public function init()
    {
        on(ServerTask::AFTER_TASK, [$this, 'destroy']);
        on(ServerRequest::AFTER_REQUEST, [$this, 'release']);
        on('SERVER_BEFORE_WORKER', [$this, 'init_channel_connection']);

    }


	/**
	 * @throws ComponentException
	 * @throws ConfigException
	 * @throws Exception
	 */
    public function init_channel_connection()
    {
    	/** @var RedisClient $connections */
        $connections = \BeReborn::$app->get('redis_connections');

	    $data = Config::get('clients.pool.max', false, 10);

	    $config = $this->get_config();

        $connections->initConnections('Redis:' . $config['host'], true ,$data);
    }

    /**
     * @param $index
     * @param $path
     * @throws Exception
     */
    public function export($index, $path = null)
    {
        $config = [
            'class' => Export::class,
            'redis' => $this->proxy(),
            'index' => $index
        ];

        /** @var Export $class */
        $class = \BeReborn::createObject($config);
        $class->saveTo($path);
    }

    /**
     * @param $index
     * @param null $path
     * @throws Exception
     */
    public function implode($index, $path = null)
    {
        $config = [
            'class' => Implode::class,
            'redis' => $this->proxy(),
            'index' => $index
        ];

        /** @var Implode $class */
        $class = \BeReborn::createObject($config);
        $class->implode($path);
    }

    /**
     * @param $name
     * @param $arguments
     * @return mixed
     * @throws
     */
    public function __call($name, $arguments)
    {
        try {
            if (method_exists($this, $name)) {
                $data = $this->{$name}(...$arguments);
            } else {
                $data = $this->proxy()->{$name}(...$arguments);
            }
        } catch (\Throwable $exception) {
            $this->error(print_r($exception->getMessage(), true));
            $data = false;
        } finally {
            return $data;
        }
    }

    /**
     * 释放连接池
     */
    public function release()
    {
	    /** @var RedisClient $connections */
	    $connections = \BeReborn::$app->get('redis_connections');
        $connections->release($this->get_config(), true);
    }

    /**
     * 销毁连接池
     */
    public function destroy()
    {
	    /** @var RedisClient $connections */
	    $connections = \BeReborn::$app->get('redis_connections');
        $connections->destroy($this->get_config(), true);
    }

    /**
     * @return \Redis
     * @throws Exception
     */
    public function proxy()
    {
        /** @var RedisClient $connections */
        $connections = \BeReborn::$app->get('redis_connections');

        $config = $this->get_config();

        $client = $connections->get($config, true);
        if (!($client instanceof \Redis)) {
            throw new Exception('Redis connections more.');
        }
        return $client;
    }

    /**
     * @return array
     */
    public function get_config(): array
    {
        $params['host'] = env('REDIS.HOST', $this->host);
        $params['port'] = env('REDIS.PORT', $this->port);
        $params['auth'] = env('REDIS.PASSWORD', $this->auth);
        $params['timeout'] = env('REDIS.TIMEOUT', 2);
        $params['databases'] = env('REDIS.DATABASE', $this->databases);
        $params['read_timeout'] = env('REDIS.READ_TIMEOUT', 10);
        $params['prefix'] = env('REDIS.PREFIX', '');
        return $params;
    }

}
